<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Multi-Sheet Import with x-spreadsheet</title>
    <link rel="stylesheet" href="https://unpkg.com/x-data-spreadsheet@1.1.9/dist/xspreadsheet.css">
    <script src="https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js"></script>
    <script src="./xspreadsheet.js"></script>
    <script src="zh-cn.js"></script>
</head>

<body>
    <h2>Excel Sheet Import and Switcher</h2>
    <input type="file" id="fileInput"> 导入文件</input>
    <button type="button" id="fileOutput">导出文件</button>
    <button type="button" id="clearTable">清空表格</button>

    <!-- 用于切换 Sheet 页的下拉菜单 -->
    <select id="sheetSelector"></select>

    <div id="xspreadsheet"></div>

    <script type="module">
        import * as xlsx from 'https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js';
        console.log('XLSX loaded:', xlsx);
        // import XLSX from 'https://cdn.sheetjs.com/xlsx-js-style/xlsx.full.min.js';
        // console.log('XLSX-js-style loaded:', XLSX);
    </script>


    <script>


        function stox1(wb) {
            var out = [];
            wb.SheetNames.forEach(function (name) {
                var o = { name: name, rows: {}, styles: [] };
                var ws = wb.Sheets[name];
                if (!ws || !ws["!ref"]) return;
                var range = XLSX.utils.decode_range(ws['!ref']);
                range.s = { r: 0, c: 0 };
                var aoa = XLSX.utils.sheet_to_json(ws, {
                    raw: false,
                    header: 1,
                    range: range
                });

                aoa.forEach(function (r, i) {
                    var cells = {};
                    r.forEach(function (c, j) {
                        cells[j] = { text: c };
                        var cellRef = XLSX.utils.encode_cell({ r: i, c: j });

                        if (ws[cellRef] != null && ws[cellRef].f != null) {
                            cells[j].text = "=" + ws[cellRef].f;
                        }

                        if (ws[cellRef] != null && ws[cellRef].s != null) {
                            var styleIndex = o.styles.indexOf(ws[cellRef].s);
                            if (styleIndex === -1) {
                                styleIndex = o.styles.push(ws[cellRef].s) - 1;
                            }
                            cells[j].style = styleIndex;
                        }
                    });
                    o.rows[i] = { cells: cells };

                    if (ws["!rows"] && ws["!rows"][i]) {
                        o.rows[i].height = ws["!rows"][i].hpt * 1.25;
                    }
                });

                o.merges = [];
                (ws["!merges"] || []).forEach(function (merge) {
                    if (o.rows[merge.s.r] == null) {
                        o.rows[merge.s.r] = { cells: {} };
                    }
                    if (o.rows[merge.s.r].cells[merge.s.c] == null) {
                        o.rows[merge.s.r].cells[merge.s.c] = {};
                    }

                    o.rows[merge.s.r].cells[merge.s.c].merge = [
                        merge.e.r - merge.s.r,
                        merge.e.c - merge.s.c
                    ];

                    o.merges.push(XLSX.utils.encode_range(merge));
                });

                o.cols = {};
                Object.keys(ws["!cols"] || {}).forEach(function (key) {
                    var col = ws["!cols"][key];
                    o.cols[key] = {
                        width: col.wpx * 1.5
                    };
                });

                out.push(o);
            });

            out.forEach(function (o) {
                o.styles = o.styles.map(converStyleFields);
            });

            return out;
        }

        function stox(wb) {
            var out = [];
            wb.SheetNames.forEach(function (name) {
                var o = { name: name, rows: {}, styles: [] };
                var ws = wb.Sheets[name];
                if (!ws || !ws["!ref"]) return;
                var range = XLSX.utils.decode_range(ws['!ref']);
                range.s = { r: 0, c: 0 };  // 修改：确保读取整个表格数据
                var aoa = XLSX.utils.sheet_to_json(ws, {
                    raw: false,
                    header: 1,
                    range: range
                });

                aoa.forEach(function (r, i) {
                    var cells = {};
                    r.forEach(function (c, j) {
                        if (c == null) c = "";  // 修改：处理空值
                        cells[j] = { text: c };
                        var cellRef = XLSX.utils.encode_cell({ r: i, c: j });

                        if (ws[cellRef] != null && ws[cellRef].f != null) {
                            cells[j].text = "=" + ws[cellRef].f;
                        }

                        if (ws[cellRef] != null && ws[cellRef].s != null) {
                            var styleIndex = o.styles.indexOf(ws[cellRef].s);
                            if (styleIndex === -1) {
                                styleIndex = o.styles.push(ws[cellRef].s) - 1;
                            }
                            cells[j].style = styleIndex;
                        }
                    });
                    o.rows[i] = { cells: cells };

                    if (ws["!rows"] && ws["!rows"][i]) {
                        o.rows[i].height = ws["!rows"][i].hpt * 1.25;
                    }
                });

                o.merges = [];
                (ws["!merges"] || []).forEach(function (merge) {
                    if (o.rows[merge.s.r] == null) {
                        o.rows[merge.s.r] = { cells: {} };
                    }
                    if (o.rows[merge.s.r].cells[merge.s.c] == null) {
                        o.rows[merge.s.r].cells[merge.s.c] = {};
                    }

                    o.rows[merge.s.r].cells[merge.s.c].merge = [
                        merge.e.r - merge.s.r,
                        merge.e.c - merge.s.c
                    ];

                    o.merges.push(XLSX.utils.encode_range(merge));
                });

                o.cols = {};
                Object.keys(ws["!cols"] || {}).forEach(function (key) {
                    var col = ws["!cols"][key];
                    o.cols[key] = {
                        width: col.wpx * 1.5
                    };
                });

                out.push(o);
            });

            out.forEach(function (o) {
                o.styles = o.styles.map(converStyleFields);
            });

            return out;
        }

        function converStyleFields(style) {
            if (style.fgColor) {
                style.bgcolor = "#" + style.fgColor.rgb;
            }
            return style;
        }


        function xtos(sdata) {
            var out = XLSX.utils.book_new();
            sdata.forEach(function (xws) {
                var ws = {};
                var rowobj = xws.rows;
                var cols = xws.cols;//列宽
                var styles = xws.styles || [];//样式
                var styleMap = {};

                // 1. 初始化样式映射(只转换了基础样式，其他复杂样式根据需要添加)
                styles.forEach((style, index) => {
                    let xf = {};
                    if (style.color) {
                        xf.font = { color: { rgb: style.color.substring(1) } };
                    }
                    if (style.bgcolor) {
                        xf.fill = { fgColor: { rgb: style.bgcolor.substring(1) } };
                    }
                    if (style.bold) {
                        xf.font.bold = style.bold;
                    }
                    if (style.size) {
                        xf.font.sz = style.sz;
                    }
                    if (style.align || style.valign) {
                        xf.alignment = { horizontal: style.align, vertical: style.valign, wrapText: true };
                    }
                    styleMap[index] = xf;
                });

                var minCoord = { r: 0, c: 0 }, maxCoord = { r: 0, c: 0 };
                for (var ri = 0; ri < rowobj.len; ++ri) {
                    var row = rowobj[ri];
                    if (!row) continue;

                    Object.keys(row.cells).forEach(function (k) {
                        var idx = +k;
                        if (isNaN(idx)) return;

                        var lastRef = XLSX.utils.encode_cell({ r: ri, c: idx });
                        if (ri > maxCoord.r) maxCoord.r = ri;
                        if (idx > maxCoord.c) maxCoord.c = idx;

                        var cellText = row.cells[k].text, type = "s";
                        if (!cellText) {
                            cellText = "";
                            type = "z";
                        } else if (!isNaN(Number(cellText))) {
                            cellText = Number(cellText);
                            type = "n";
                        } else if (cellText.toLowerCase() === "true" || cellText.toLowerCase() === "false") {
                            cellText = Boolean(cellText);
                            type = "b";
                        }

                        ws[lastRef] = { v: cellText, t: type };

                        if (type == "s" && cellText[0] == "=") {
                            ws[lastRef].f = cellText.slice(1);
                        }

                        // 2. 添加样式
                        var styleIndex = row.cells[k].style;
                        if (styleIndex in styleMap) {
                            ws[lastRef].s = styleMap[styleIndex];
                        }

                        // 3. 设置行高
                        if (row.height != null) {
                            if (ws["!rows"] == null) ws["!rows"] = [];
                            ws["!rows"][ri] = { hpx: row.height };
                        }

                        if (row.cells[k].merge != null) {
                            if (ws["!merges"] == null) ws["!merges"] = [];

                            ws["!merges"].push({
                                s: { r: ri, c: idx },
                                e: {
                                    r: ri + row.cells[k].merge[0],
                                    c: idx + row.cells[k].merge[1]
                                }
                            });
                        }
                    });
                }
                ws["!ref"] = minCoord ? XLSX.utils.encode_range({
                    s: minCoord,
                    e: maxCoord
                }) : "A1";

                // 4. 设置列宽
                let columns = []
                // 遍历 cols 对象的每一个键值对
                Object.keys(cols).forEach(key => {
                    const colConfig = cols[key];
                    if (key !== 'len' && 'width' in colConfig) {
                        columns[key] = { wpx: colConfig.width };
                    }
                });
                // 将列配置数组赋值给 ws['!cols']
                ws['!cols'] = columns;

                XLSX.utils.book_append_sheet(out, ws, xws.name);
            });

            return out;
        }

        function xtos1(sdata) {
            var out = XLSX.utils.book_new();
            sdata.forEach(function (xws) {
                var ws = {};
                var rowobj = xws.rows;
                var cols = xws.cols;
                var styles = xws.styles || [];
                var styleMap = {};

                styles.forEach((style, index) => {
                    let xf = {};
                    if (style.color) {
                        xf.font = { color: { rgb: style.color.substring(1) } };
                    }
                    if (style.bgcolor) {
                        xf.fill = { fgColor: { rgb: style.bgcolor.substring(1) } };
                    }
                    if (style.bold) {
                        xf.font.bold = style.bold;
                    }
                    if (style.size) {
                        xf.font.sz = style.sz;
                    }
                    if (style.align || style.valign) {
                        xf.alignment = { horizontal: style.align, vertical: style.valign, wrapText: true };
                    }
                    styleMap[index] = xf;
                });

                var minCoord = { r: 0, c: 0 }, maxCoord = { r: 0, c: 0 };
                for (var ri = 0; ri < rowobj.len; ++ri) {
                    var row = rowobj[ri];
                    if (!row) continue;

                    Object.keys(row.cells).forEach(function (k) {
                        var idx = +k;
                        if (isNaN(idx)) return;

                        var lastRef = XLSX.utils.encode_cell({ r: ri, c: idx });
                        if (ri > maxCoord.r) maxCoord.r = ri;
                        if (idx > maxCoord.c) maxCoord.c = idx;

                        var cellText = row.cells[k].text, type = "s";
                        if (!cellText) {
                            cellText = "";
                            type = "z";
                        } else if (!isNaN(Number(cellText))) {
                            cellText = Number(cellText);
                            type = "n";
                        } else if (cellText.toLowerCase() === "true" || cellText.toLowerCase() === "false") {
                            cellText = Boolean(cellText);
                            type = "b";
                        }

                        ws[lastRef] = { v: cellText, t: type };

                        if (type === "s" && cellText[0] === "=") {
                            ws[lastRef].f = cellText.slice(1);
                        }

                        var styleIndex = row.cells[k].style;
                        if (styleIndex in styleMap) {
                            ws[lastRef].s = styleMap[styleIndex];
                        }

                        if (row.cells[k].merge != null) {
                            if (ws["!merges"] == null) ws["!merges"] = [];

                            ws["!merges"].push({
                                s: { r: ri, c: idx },
                                e: {
                                    r: ri + row.cells[k].merge[0],
                                    c: idx + row.cells[k].merge[1]
                                }
                            });
                        }
                    });
                }
                ws["!ref"] = XLSX.utils.encode_range({
                    s: minCoord,
                    e: maxCoord
                });

                ws["!cols"] = Object.keys(cols).map(key => cols[key].width ? { wpx: cols[key].width } : {});

                XLSX.utils.book_append_sheet(out, ws, xws.name);
            });

            return out;
        }

        // document.addEventListener('DOMContentLoaded', function () {
        //     const xs = x_spreadsheet('#xspreadsheet', {});
        //     const fileInput = document.getElementById('fileInput');
        //     const fileOutputButton = document.getElementById('fileOutput');
        //     const clearTableButton = document.getElementById('clearTable');
        //     const sheetSelector = document.getElementById('sheetSelector');

        //     let allSheets = [];

        //     // 文件导入
        //     fileInput.addEventListener('change', async function (event) {
        //         const files = event.target.files;
        //         if (files.length > 0) {
        //             const reader = new FileReader();
        //             reader.onload = (e) => {
        //                 const workbook = XLSX.read(e.target.result, { type: 'array', cellStyles: true });
        //                 allSheets = stox(workbook);

        //                 // 填充下拉菜单
        //                 sheetSelector.innerHTML = '';
        //                 allSheets.forEach((sheet, index) => {
        //                     const option = document.createElement('option');
        //                     option.value = index;
        //                     option.textContent = sheet.name;
        //                     sheetSelector.appendChild(option);
        //                 });

        //                 // 默认加载第一个 sheet
        //                 xs.loadData(allSheets[0]);
        //             };
        //             reader.readAsArrayBuffer(files[0]);
        //         }
        //     });

        //     // 切换 sheet 页
        //     sheetSelector.addEventListener('change', function () {
        //         const selectedSheetIndex = parseInt(sheetSelector.value, 10);
        //         xs.loadData(allSheets[selectedSheetIndex]);
        //     });

        //     // 文件导出
        //     fileOutputButton.addEventListener('click', function () {
        //         if (xs !== null) {
        //             const data = xs.getData(); // 获取当前表格的数据
        //             const worksheet = xtos(Object.values(data)); // 将数据转换为适当的格式
        //             XLSX.writeFile(worksheet, "SheetJS.xlsx"); // 写入文件
        //         }
        //     });

        //     // 清空表格
        //     clearTableButton.addEventListener('click', function () {
        //         xs.loadData({});
        //     });
        // });


        // document.addEventListener('DOMContentLoaded', function () {
        //     const xs = x_spreadsheet('#xspreadsheet', {});
        //     const fileInput = document.getElementById('fileInput');
        //     const fileOutputButton = document.getElementById('fileOutput');
        //     const clearTableButton = document.getElementById('clearTable');

        //     let allSheets = [];

        //     // 文件导入
        //     fileInput.addEventListener('change', async function (event) {
        //         const files = event.target.files;
        //         if (files.length > 0) {
        //             const reader = new FileReader();
        //             reader.onload = (e) => {
        //                 const workbook = XLSX.read(e.target.result, { type: 'array', cellStyles: true });
        //                 allSheets = stox(workbook); // 确保 stox 返回的结构正确
        //                 console.log("所有工作表数据:", allSheets); // 输出所有工作表信息

        //                 // 清空现有数据
        //                 xs.loadData({});

        //                 // 添加每个 sheet 到 x-spreadsheet
        //                 allSheets.forEach(sheet => {
        //                     console.log("处理工作表:", sheet.name); // 输出当前正在处理的工作表名称
        //                     if (sheet.name && sheet.rows) { // 确保有 name 和 rows
        //                         const data = [];

        //                         // 将 rows 转换为适合 x-spreadsheet 的格式
        //                         for (let rowIndex in sheet.rows) {
        //                             const row = sheet.rows[rowIndex].cells;
        //                             const rowData = [];
        //                             for (let colIndex in row) {
        //                                 rowData[colIndex] = row[colIndex].text || ""; // 提取单元格的文本或空值
        //                             }
        //                             data.push(rowData);
        //                         }

        //                         console.log("添加工作表:", sheet.name, "数据:", data); // 输出添加的工作表数据

        //                         // 确保将工作表添加至 x-spreadsheet
        //                         xs.addSheet(sheet.name, {
        //                             data: data, // 将数据传递给工作表
        //                             styles: sheet.styles || [], // 添加样式
        //                             merges: sheet.merges || [], // 添加合并单元格
        //                             cols: sheet.cols || {}, // 添加列宽等信息
        //                         });
        //                     } else {
        //                         console.warn('忽略无效工作表:', sheet);
        //                     }
        //                 });

        //                 // 默认加载第一个 sheet 的数据
        //                 if (allSheets.length > 0) {
        //                     console.log("加载默认工作表数据:", allSheets[0].name); // 输出加载的默认工作表
        //                     xs.loadData(allSheets[0].rows); // 确保加载第一个工作表的数据
        //                 }
        //             };
        //             reader.readAsArrayBuffer(files[0]);
        //         }
        //     });

        //     // 文件导出
        //     fileOutputButton.addEventListener('click', function () {
        //         if (xs !== null) {
        //             const data = xs.getData(); // 获取当前表格的数据
        //             const worksheet = xtos(Object.values(data)); // 将数据转换为适当的格式
        //             console.log("导出数据:", worksheet); // 输出待导出的数据
        //             XLSX.writeFile(worksheet, "SheetJS.xlsx"); // 写入文件
        //         }
        //     });

        //     // 清空表格
        //     clearTableButton.addEventListener('click', function () {
        //         console.log("清空当前工作表"); // 输出清空操作
        //         xs.loadData({}); // 清空当前工作表
        //     });
        // });




        // document.addEventListener('DOMContentLoaded', function () {
        //     const xs = x_spreadsheet('#xspreadsheet', {});
        //     const fileInput = document.getElementById('fileInput');
        //     const fileOutputButton = document.getElementById('fileOutput');
        //     const clearTableButton = document.getElementById('clearTable');

        //     let allSheets = [];

        //     // 文件导入
        //     fileInput.addEventListener('change', async function (event) {
        //         const files = event.target.files;
        //         if (files.length > 0) {
        //             const reader = new FileReader();
        //             reader.onload = (e) => {
        //                 const workbook = XLSX.read(e.target.result, { type: 'array', cellStyles: true });
        //                 allSheets = stox(workbook);
        //                 console.log("所有工作表数据:", allSheets);

        //                 // 清空现有数据
        //                 xs.loadData({});

        //                 allSheets.forEach(sheet => {
        //                     console.log("处理工作表:", sheet.name);
        //                     if (sheet.name && sheet.rows) {
        //                         const data = [];

        //                         for (let rowIndex in sheet.rows) {
        //                             const row = sheet.rows[rowIndex].cells;
        //                             const rowData = [];
        //                             let hasValidCell = false;

        //                             // 检查有效单元格
        //                             for (let colIndex in row) {
        //                                 const cellValue = row[colIndex].text || "";
        //                                 rowData[colIndex] = cellValue;

        //                                 if (cellValue) {
        //                                     hasValidCell = true;
        //                                 }
        //                             }

        //                             // 只有在行中存在有效单元格内容时，才添加该行
        //                             if (hasValidCell) {
        //                                 data.push(rowData);
        //                             }
        //                         }

        //                         console.log("添加工作表:", sheet.name, "数据:", data);
        //                         xs.addSheet(sheet.name, {
        //                             data: data,
        //                             styles: sheet.styles || [],
        //                             merges: sheet.merges || [],
        //                             cols: sheet.cols || {},
        //                         });
        //                     } else {
        //                         console.warn('忽略无效工作表:', sheet);
        //                     }
        //                 });

        //                 // 加载第一个有效工作表数据
        //                 if (data.length > 0) {
        //                     console.log("加载默认工作表数据:", allSheets[0].name);
        //                     xs.loadData(allSheets[0].rows);
        //                 }
        //             };
        //             reader.readAsArrayBuffer(files[0]);
        //         }
        //     });

        //     // 文件导出
        //     fileOutputButton.addEventListener('click', function () {
        //         if (xs !== null) {
        //             const data = xs.getData();
        //             const worksheet = xtos(Object.values(data));
        //             console.log("导出数据:", worksheet);
        //             XLSX.writeFile(worksheet, "SheetJS.xlsx");
        //         }
        //     });

        //     // 清空表格
        //     clearTableButton.addEventListener('click', function () {
        //         console.log("清空当前工作表");
        //         xs.loadData({});
        //     });
        // });



        document.addEventListener('DOMContentLoaded', function () {
            const xs = x_spreadsheet('#xspreadsheet', {});
            const fileInput = document.getElementById('fileInput');
            const fileOutputButton = document.getElementById('fileOutput');
            const clearTableButton = document.getElementById('clearTable');

            let allSheets = [];

            // 文件导入
            fileInput.addEventListener('change', async function (event) {
                try {
                    const files = event.target.files;
                    if (files.length > 0) {
                        console.log("开始读取文件...");
                        const reader = new FileReader();
                        reader.onload = (e) => {
                            try {
                                console.log("文件读取成功，解析中...");
                                const workbook = XLSX.read(e.target.result, { type: 'array', cellStyles: true });
                                allSheets = stox(workbook);
                                console.log("所有工作表数据解析完成:", allSheets);

                                // 清空现有数据
                                xs.loadData({});

                                // Example: Ensure the data is properly formatted and fully loaded
                                allSheets.forEach((sheet, index) => {
                                    console.log(`处理工作表 ${index + 1}: ${sheet.name}`);
                                    if (sheet.name && sheet.rows) {
                                        const data = [];
                                        Object.keys(sheet.rows).forEach((rowIndex) => {
                                            const row = sheet.rows[rowIndex].cells;
                                            const rowData = [];
                                            Object.keys(row).forEach((colIndex) => {
                                                const cellValue = row[colIndex]?.text || "";
                                                rowData[colIndex] = cellValue;
                                            });
                                            data.push(rowData);
                                        });

                                        // 修复：在确认数据格式正确后，调用addSheet
                                        xs.addSheet(sheet.name, {
                                            data: data,
                                            styles: sheet.styles || [],
                                            merges: sheet.merges || [],
                                            cols: sheet.cols || {},  // 确保列宽定义存在
                                        });

                                        console.log(`工作表 "${sheet.name}" 已加载`);
                                    } else {
                                        console.warn(`忽略无效工作表: ${sheet.name || '未命名工作表'}`);
                                    }
                                });

                                // 确保正确渲染第一个工作表
                                xs.loadData(allSheets);  // 如果有此方法，加载所有数据
                                xs.render();  // 触发渲染


                                // 自动切换到第一个工作表
                                if (allSheets.length > 0) {
                                    console.log(`切换到第一个工作表 "${allSheets[0].name}"`);
                                    xs.loadData({ data: allSheets[0].rows });
                                } else {
                                    console.warn("未找到有效数据，无法加载到表格中。");
                                }
                            } catch (error) {
                                console.error("解析工作表时出错:", error);
                            }
                        };
                        reader.readAsArrayBuffer(files[0]);
                    } else {
                        console.warn("未选择文件。");
                    }
                } catch (error) {
                    console.error("文件导入过程中出现错误:", error);
                }
            });

            // 文件导出
            fileOutputButton.addEventListener('click', function () {
                try {
                    if (xs !== null) {
                        const data = xs.getData();
                        console.log("导出数据准备中:", data);
                        const worksheet = xtos(Object.values(data));
                        XLSX.writeFile(worksheet, "SheetJS.xlsx");
                        console.log("文件已成功导出为 SheetJS.xlsx");
                    } else {
                        console.warn("未初始化表格，无法导出数据。");
                    }
                } catch (error) {
                    console.error("导出数据时出错:", error);
                }
            });

            // 清空表格
            clearTableButton.addEventListener('click', function () {
                try {
                    console.log("清空当前工作表...");
                    xs.loadData({});
                    console.log("工作表已清空。");
                } catch (error) {
                    console.error("清空工作表时出错:", error);
                }
            });
        });




    </script>

</body>

</html>



<!-- fillImage(box: Box, cell: any, { fixWidth, fixHeight }: { fixWidth: number, fixHeight: number }, callback?: (width: number, height: number) => void) {
    const { x, y, width, height } = box;
    const dx = x + fixWidth;
    const dy = y + fixHeight;
    const { startRowIndex, startColIndex } = cell;
 
    const cellImage = this.imageCaches.get(`${startRowIndex}.${startColIndex}`);
    if (cellImage) {
      this.save()
      this.clearRect(x, y, width, height);
      this.context.drawImage(cellImage, Pixel.npx(x), Pixel.npx(y), Pixel.npx(width), Pixel.npx(height));
      this.restore();
    } else {
      const image = new Image();
      image.src = 'https://theanam.github.io/react-awesome-lightbox/img/2.jpg'
      image.onload = () => {
        this.save()
        this.context.drawImage(image, Pixel.npx(dx), Pixel.npx(dy), Pixel.npx(image.width / 10), Pixel.npx(image.height / 10));
        this.restore();
        this.imageCaches.set(`${startRowIndex}.${startColIndex}`, image)
        callback?.(Pixel.npx(image.width / 12), Pixel.npx(image.height / 12));
      }
    }
  } -->